#ifndef HTTP_MG_SERVER_H_
#define HTTP_MG_SERVER_H_

#define HTTP_MG_MAX_URI_LEN 128
#define HTTP_MG_MAX_METHOD_SUPPORT 64
#define HTTP_MG_MAX_HANDLE_SUPPORT 64


typedef void* HTTP_MG_HANDLE;

typedef enum 
{
    METHOD_RET_PROCESSED = 0,
    METHOD_RET_NOPROCESS,
} HTTP_MG_METHOD_RET_E;

typedef enum 
{
    HTTP_STATUS_CONTINUE = 100,
    HTTP_STATUS_SWITCHING_PROTOCOLS = 101,
    HTTP_STATUS_OK = 200,
    HTTP_STATUS_CREATED = 201,
    HTTP_STATUS_ACCEPTED = 202,
    HTTP_STATUS_NON_AUTHORITATIVE_INFORMATION = 203,
    HTTP_STATUS_NO_CONTENT = 204,
    HTTP_STATUS_RESET_CONTENT = 205,
    HTTP_STATUS_PARTIAL_CONTENT = 206,
    HTTP_STATUS_MULTIPLE_CHOICES = 300,
    HTTP_STATUS_MOVED_PERMANENTLY = 301,
    HTTP_STATUS_FOUND = 302,
    HTTP_STATUS_SEE_OTHER = 303,
    HTTP_STATUS_NOT_MODIFIED = 304,
    HTTP_STATUS_USE_PROXY = 305,
    HTTP_STATUS_TEMPORARY_REDIRECT = 307,
    HTTP_STATUS_BAD_REQUEST = 400,
    HTTP_STATUS_UNAUTHORIZED = 401,
    HTTP_STATUS_PAYMENT_REQUIRED = 402,
    HTTP_STATUS_FORBIDDEN = 403,
    HTTP_STATUS_NOT_FOUND = 404,
    HTTP_STATUS_METHOD_NOT_ALLOWED = 405,
    HTTP_STATUS_NOT_ACCEPTABLE = 406,
    HTTP_STATUS_PROXY_AUTHENTICATION_REQUIRED = 407,
    HTTP_STATUS_REQUEST_TIME_OUT = 408,
    HTTP_STATUS_CONFLICT = 409,
    HTTP_STATUS_GONE = 410,
    HTTP_STATUS_LENGTH_REQUIRED = 411,
    HTTP_STATUS_PRECONDITION_FAILED = 412,
    HTTP_STATUS_REQUEST_ENTITY_TOO_LARGE = 413,
    HTTP_STATUS_REQUEST_URL_TOO_LARGE = 414,
    HTTP_STATUS_UNSUPPORTED_MEDIA_TYPE = 415,
    HTTP_STATUS_REQUESTED_RANGE_NOT_SATISFIABLE = 416,
    HTTP_STATUS_EXPECTATION_FAILED = 417,
    HTTP_STATUS_INTERNAL_SERVER_ERROR = 500,
    HTTP_STATUS_NOT_IMPLEMENTED = 501,
    HTTP_STATUS_BAD_GATEWAY = 502,
    HTTP_STATUS_SERVICE_UNAVAILABLE = 503,
    HTTP_STATUS_GATEWAY_TIME_OUT = 504,
    HTTP_STATUS_HTTP_VERSION_NOT_SUPPORTED = 505,
}HTTP_RESPONSE_STATUS_CODE;

typedef struct 
{
  char *request_method;  // "GET", "POST", etc
  char *uri;             // URL-decoded URI
  char *http_version;    // E.g. "1.0", "1.1"
  char *query_string;    // URL part after '?' (not including '?') or NULL
  char *remote_user;     // Authenticated user, or NULL if no auth used
  long remote_ip;        // Client's IP address
  int remote_port;       // Client's port
  int num_headers;       // Number of headers
  struct header {
    char *name;          // HTTP header name
    char *value;         // HTTP header value
  } http_headers[64];    // Maximum 64 headers
} http_mg_req_info;


/**
 * http_mg_method_t prototype of http method.
 */
typedef HTTP_MG_METHOD_RET_E (*http_mg_method_t)(HTTP_MG_HANDLE h, http_mg_req_info *req_info);


/* http_mg_server_start
 *
 * Start ALi default http server for media.
 *
 * return TRUE if success; FALSE if failure.
 */
BOOL http_mg_server_start(void);

/* http_mg_server_stop
 *
 * Stop ALi default http server for media.
 */
void http_mg_server_stop(void);

/* http_mg_server_send_file
 *
 * Use to send one file in http response content.
 *
 * @h This connection handle.
 * @full_path The file's full path from root directory.
 */
void http_mg_server_send_file(HTTP_MG_HANDLE h, const char *full_path);

/* http_mg_server_read
 *
 * Read data from this connection, e.g. POST body data.
 *
 * @h The handle of this connection.
 * @buf The data buffer use to store data.
 * @len The data buffer's length.
 * 
 * return The byte count have read.
 */
INT32 http_mg_server_read(HTTP_MG_HANDLE h, UINT8 *buf, UINT32 len);

/* http_mg_server_write
 *
 * Send data out to client.
 *
 * @h This connection handle.
 * @buf The data buffer going to send out.
 * @len The data buffer's data length.
 *
 * return The byte count have sent out.
 */
INT32 http_mg_server_write(HTTP_MG_HANDLE h, UINT8 *buf, UINT32 len);

/* http_mg_quick_response
 *
 * Use to send out some response.
 * 
 * @h This connection handle.
 * @error_status_code response code, ref to HTTP_RESPONSE_STATUS_CODE.
 * 
 * return TRUE if send success; FALSE if send failure or this response code no quick implement.
 */
BOOL http_mg_quick_response(HTTP_MG_HANDLE h, INT32 error_status_code);

/* http_mg_method_register
 * 
 * Register method callback to http mg server with unique uri, 
 * e.g. uri = "/a/b/c/test_method", method=mytest_method, when client request "http://IP:PORT/a/b/c/test_method",
 * server will callback to function mytest_method, you can do your process in this function, and you need send out
 * all response content(include headers) as http request response.
 *
 * @uri The uri that you want to identify your method.
 * @method The callback function you want to be called.
 * 
 * return TRUE if register success; FALSE if failure.
 */
BOOL http_mg_method_register(char *uri, http_mg_method_t method);

/* http_mg_method_unregister
 *
 * Unregister the method in the specified uri.
 * @uri The URI going to unregister.
 */
void http_mg_method_unregister(char *uri);

/* http_mg_server_is_started
 *
 * Check is http mg server is started.
 *
 * return TRUE if server already started; FALSE if server is not started.
 */
BOOL http_mg_server_is_started(void);

/* http_mg_get_header
 *
 * Get HTTP header's value from this request.
 * 
 * @h This connection handle.
 * @name Header name.
 *
 * return The header's value if success, don't free this pointer.
 */
char *http_mg_get_header(HTTP_MG_HANDLE h, const char *name);

/* http_mg_parse_range_header
 *
 * Get Range header's value.
 * 
 * @header Range header's value string
 * @a range begin value
 * @b range end value
 *
 * return The parsed value count.
 */
INT32 http_mg_parse_range_header(const char *header, INT64 *a, INT64 *b);


/******************************************************************************************/
// add by ALi for manage the http connection

#define HTTP_DEF_MAX_CLIENT  2
#define HTTP_DEF_MAX_CLIENT_UP 10//2//1 // Oncer: for client close this socket, but server's select can not detect this...
#define HTTP_DEF_MAX_CLIENT_DOWN 2
#define HTTP_DEF_MAX_CLIENT_SMALL 1
#define HTTP_DEF_MAX_TASK   10
//initialize the http server connect max number
typedef struct
{
    int max_client;             //max client number
    int max_client_download;    //max download task number per client(on line paly, download, get file info)
    int max_client_upload;      //max upload task number per client(upload file)
    int max_client_small_data;  //max small data(delete file,etc)
    int max_task;               //max toatal task number
}http_connect_set_t;

typedef enum{
    HTTP_CONNECT_TYPE_UPLOAD,
    HTTP_CONNECT_TYPE_DOWNLOAD,
    HTTP_CONNECT_TYPE_SMALL_DATA,
}HTTP_CONNECT_TYPE;

typedef struct
{
    int download_task_num;
    int upload_task_num;
    int samll_data_num;
    unsigned int client_ip; //0xAABBCCDD => 0xAA.BB.CC.DD(ip)
    int used;
}http_connect_info_t;

int http_connect_mgr_init(http_connect_set_t *connect_set);
int http_connect_mgr_push(struct mg_connection *conn);
void http_connect_mgr_pop(struct mg_connection *conn);
void http_connect_mgr_release(void);

/******************************************************************************************/


#endif //HTTP_MG_SERVER_H_

